﻿using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Text;
using DotNet.Common;
using System.Collections.Generic;
using System.IO;

namespace TextCmd
{
	public partial class FormCmd : Form
	{
		Commander m_commander;
		XMLConfig<ConfigData> m_configData;
		FormDragArg m_formDragArg;
		string m_lastStr;

		public FormCmd()
		{
			InitializeComponent();

			Control.CheckForIllegalCrossThreadCalls = false;
		}

		private void FormCmd_Load(object sender, EventArgs e)
		{
			m_configData = new XMLConfig<ConfigData>();
			if (!m_configData.Load(Application.StartupPath + @"\TextCmd.xml"))
			{
				m_configData.Data.CmdFilePath = Environment.GetEnvironmentVariable("comspec");
			}
			AddAutoCompleteList();

			m_commander = new Commander();
			m_commander.Load(m_configData.Data.CmdFilePath);
			m_commander.OnRunStart += new MethodInvoker(commander_OnRunStart);
			m_commander.OnRunStop += new MethodInvoker(commander_OnRunStop);
			m_commander.OnOutputData += new StringInvoker(commander_OnOutputData);

			m_formDragArg = new FormDragArg();
			m_formDragArg.Load(this, null, OpenFileLink);
			m_lastStr = string.Empty;

			this.Text = "命令提示符 " + m_configData.Data.CmdFilePath;
		}

		private void FormCmd_FormClosed(object sender, FormClosedEventArgs e)
		{
			m_configData.Unload();
			m_commander.UnLoad();
		}

		void commander_OnRunStart()
		{
			btnOK.Enabled = false;
			textCmd.ReadOnly = true;
		}

		void commander_OnRunStop()
		{
			btnOK.Enabled = true;
			textCmd.Focus();
			textCmd.ReadOnly = false;
		}

		void commander_OnOutputData(string str)
		{
			StringBuilder builder = new StringBuilder(textResult.Text);

			switch (str.Length)
			{
				case 0:
					if (m_lastStr.Length != 0)
					{
						m_lastStr = string.Empty;
						return;
					}
					break;
				case 1:
					if (char.IsControl(str[0]))
					{
						switch (str[0])
						{
							case '\f':
								textResult.Clear();
								break;
						}
						return;
					}
					break;
				default:
					break;
			}

			builder.AppendLine(str);
			textResult.Text = builder.ToString();
			textResult.SelectionStart = builder.Length;
			textResult.ScrollToCaret();

			m_lastStr = str;
		}

		private void btnOK_Click(object sender, EventArgs e)
		{
			textCmd.SelectAll();
			AddCmdToList(textCmd.Text);
			m_commander.Run(textCmd.Text);
		}

		private void textCmd_TextChanged(object sender, EventArgs e)
		{
			btnOK.Enabled = textCmd.Text.Length != 0;
		}

		private void FormCmd_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (e.KeyChar == '\x3')
			{
				m_commander.Run(e.KeyChar.ToString());
			}
			if (!textCmd.Focused)
			{
				textCmd.Focus();
				if (!char.IsControl(e.KeyChar))
				{
					textCmd.SelectedText = e.KeyChar.ToString();
				}
			}
		}

		private void textCmd_Enter(object sender, EventArgs e)
		{
			textCmd.SelectAll();
		}

		void AddCmdToList(string cmd)
		{
			if (m_configData.Data.HistoryCmdList == null)
			{
				m_configData.Data.HistoryCmdList = new List<HistoryCmd>();
			}

			List<HistoryCmd> cmdList = m_configData.Data.HistoryCmdList;
			HistoryCmd Command;

			int index;
			int count = cmdList.Count;
			int moveCount = 0,moveIndex = 0;
			for (index = 0; index < count; index++)
			{
				Command = cmdList[index];

				if (Command.Count != moveCount)
				{
					moveCount = Command.Count;
					moveIndex = index;
				}

				if (string.Compare(cmd,Command.Cmd, true) == 0)
				{
					Command.Count++;
					if (index != moveIndex)
					{
						HistoryCmd temp = cmdList[moveIndex];
						cmdList[moveIndex] = Command;
						cmdList[index] = temp;
					}
					return;
				}
			}

			if (index == count)
			{
				Command = new HistoryCmd();
				Command.Cmd = cmd;
				Command.Count = 1;
				cmdList.Add(Command);
				textCmd.AutoCompleteCustomSource.Add(cmd);
			}
		}

		void AddAutoCompleteList()
		{
			List<HistoryCmd> cmdList = m_configData.Data.HistoryCmdList;
			if(cmdList == null)
				return;

			int count = cmdList.Count;
			string[] autoCompleteList = new string[count];
			for (int i = 0; i < count; i++)
			{
				autoCompleteList[i] = cmdList[i].Cmd;
			}

			textCmd.AutoCompleteCustomSource.AddRange(autoCompleteList);
		}

		bool OpenFileLink(string filepath)
		{
			textCmd.SelectedText = filepath;
			return true;
		}
	}
}
